/**
 * 单元格框选组件(一个单元格 = 一个穴盘，一个大列 包含3小列)
 * 通过v-model双向绑定数据
 * 数据为对象数组，如果数组个数小于 columnCount*rowCount*cellColumnCountPerColumn，则会通过默认值补全，如果大于，则忽略多出来的对象。其中对象属性如下：
 * {
 *     "id": 必填，对象唯一主键，可通过配置组件的 unique-key 属性，指定唯一属性名
 *     "selected": 选填，不设置时，组件内部会自动设置为 false，true: 选中单元格, false:不选中单元格
 *     "disabled": 选填，不设置时，组件内部会自动设置为 false，true: 单元格不可选中, false:单元格可被选中
 * }
 *
 * 组件可选属性如下：
 * width：整个组件的宽度，默认：100%
 * height：整个组件的高度，默认：100%
 * columnCount：大列数(床数)，默认：15
 * rowCount：行数，默认：100
 * columnUnit：列头的单位，默认：床
 * rowUnit：行头的单位，默认：空字符串
 * disabled：是否禁用整个组件的选择功能(包括框选、点选、列选)，默认：false
 * animate：是否启用框选时显示的矩形的动画效果，默认：true
 * uniqueKey：v-model数据对象唯一主键属性名，需要与数据对象的属性一致，如：对象的唯一属性为：cellId，则需要设置该属性为：cellId，默认：id
 * disableHeaderSelect：是否禁用列头、行头选择整列、整行功能，默认：false
 * keep：true:每次框选会保留之前已选中的，false:每次框选不保留之前选中的，只选中当前框选的，默认：true
 * cellColumnCountPerColumn: 每一大列(每一床)显示的格子小列数(每一大列中，包含几小列格子)，默认：3
 * columnCountPerView：每个轮播视图展示的大列数(床数)，默认：7
 *
 * 组件可调用函数：
 * getColumnCells(column) 获取某一大列的所有单元格数据
 * toggleColumn(column, startRow, endRow) 某一大列第startRow行到第endRow行,选中状态切换，不传startRow, endRow，则整列状态切换
 * previewView() 往前滚一屏视图
 * nextView() 往后滚一屏视图
 */
const xsCellSelector = {
    model: {
        prop: 'value',
        event: 'select'
    },
    props: {
        width: {//整个组件的宽度
            type: [Number, String],
            default: '100%'
        },
        height: {//整个组件的高度度
            type: [Number, String],
            default: '100%'
        },
        columnCount: {//列数
            type: Number,
            default: 15
        },
        rowCount: {//行数
            type: Number,
            default: 20
        },
        columnUnit: {//列头的单位
            type: String,
            default: '床'
        },
        rowUnit: {//行头的单位
            type: String,
            default: ''
        },
        disabled: {//是否禁用框选功能
            type: Boolean,
            default: false
        },
        animate: {//框选矩形 边框动画效果
            type: Boolean,
            default: true
        },
        value: {//双向绑定的值，对象数组，对象必须有uniqueKey指定的属性
            type: Array,
            default: []
        },
        uniqueKey: {//v-model或value中的对象唯一属性名
            type: String,
            default: 'id'
        },
        disableHeaderSelect: {//是否禁用列头、行头选择整列、整行功能
            type: Boolean,
            default: false
        },
        keep: {//true:每次框选会保留之前已选中的，false:每次框选不保留之前选中的，只选中当前框选的
            type: Boolean,
            default: true
        },
        cellColumnCountPerColumn: {//每列格子列数(每一大列中，包含几小列格子)
            type: Number,
            default: 3
        },
        columnCountPerView: {//每个轮播视图展示的列数
            type: Number,
            default: 7
        },
        reverse: {  //是否启用反选(鼠标从下往上框选，则取消选中 在框内的之前已选中的单元格)
            type: Boolean,
            default: true
        }
    },
    data() {
        return {
            cells: [],  //根据value生成的单元对象
            busy: false,    //框选计算繁忙标志
            dragSelectedCells: null,    //鼠标拖拽框选过程中选中的单元格

            cellsContainerWidth: 0, //格子父容器宽度(渲染后计算得到)
            cellsContainerHeight: 0,   //格子父容器高度(渲染后计算得到)
            columnWidth: 0, //一大列的宽度(渲染后计算得到)
            cellDoms: [],   //单元dom数组
            mainPanelRect: null,
            cellContainerRect: null,
            startPoint: null,   //相对于cellContainer的框选开始点坐标
            endPoint: null,  //相对于cellContainer的框选结束点坐标

            cellsContainerScrollLeft: 0,
            curView: 1, //当前视图(下标从1开始)
        }
    },
    computed: {
        /**
         * 组件容器外框样式
         * @return {{width: (string|*), height: (string|*)}}
         */
        boxSelectorStyle() {
            let width = typeof(this.width)==='number' ? this.width+'px' : this.width;
            let height = typeof(this.height)==='number' ? this.height+'px' : this.height;
            return {
                width: width,
                height: height
            }
        },
        /**
         * 每一大列的格子数
         */
        cellCountPerColumn() {
            return this.rowCount*this.cellColumnCountPerColumn;
        },
        /**
         * 格子总数
         * @return {number}
         */
        cellCount() {
            return this.columnCount*this.cellCountPerColumn;
        },
        /**
         * 视图总数
         * @return {number}
         */
        viewCount() {
            return Math.ceil(this.columnCount/this.columnCountPerView);
        },
        /**
         * 各个轮播视图 对应的 列号数组(列索引+1)
         * @return {Map<any, any>}
         */
        viewColumnsMap() {
            let map = new Map();
            for(let i=1; i<=this.viewCount; i++){
                let start = this.columnCountPerView*(i-1);
                let end = start + this.columnCountPerView;
                if(end>this.columnCount) {
                    end = this.columnCount;
                }
                let arr = [];
                for(let x=start; x<end; x++) {
                    arr.push(x+1);
                }
                map.set(i, arr);
            }
            return map;
        },
        /**
         * 每行头部样式
         */
        rowHeaderStyle() {
            let style = {};
            if(this.disabled || this.disableHeaderSelect){
                style.cursor = 'default';
            }
            return style;
        },
        headerWrapStyle() {
            return {width: this.cellsContainerWidth+'px'};
        },
        columnCellStyle() {
            let style = {
                gridTemplateColumns: 'repeat('+this.cellColumnCountPerColumn+', auto)',
            };
            return style;
        },
        columnHeaderStyle() {
            let style = {
                width: this.columnWidth+'px'
            }
            if(this.disabled || this.disableHeaderSelect){
                style.cursor = 'default';
            }
            return style;
        },
        emptyFillStyle() {
            return {
                width: this.columnWidth+'px',
                cursor: 'default'
            };
        },
        /**
         * 是否显示拖拽框
         * @return {null|*}
         */
        showDragRect() {
            return this.startPoint && this.endPoint;
        },
        /**
         * 选框样式
         */
        dragRectStyle() {
            if(this.showDragRect) {
                let width = this.endPoint.x - this.startPoint.x;
                let height = this.endPoint.y - this.startPoint.y;
                let dragWidthDis = Math.abs(width), dragHeightDis = Math.abs(height);
                let style = {
                    left: ((width > 0 ? this.startPoint.x : this.endPoint.x) + this.cellsContainerScrollLeft) + 'px',
                    top: (height > 0 ? this.startPoint.y : this.endPoint.y) + 'px',
                    width: dragWidthDis + 'px',
                    height: dragHeightDis + 'px',
                };
                return style;
            }else{
                return {};
            }
        },
        /**
         * 框选时，当前是否反选
         * @return {boolean}
         */
        isReverse() {
            if(this.showDragRect && this.reverse) {
                return this.endPoint.y<this.startPoint.y;
            }
            return false;
        },
        cellContainerStyle() {
            let style = {height: this.cellsContainerHeight+'px'};
            if(this.showDragRect) { //拖动框选时不允许横向滚动
                style.overflowX = 'hidden';
            }
            return style;
        },
        /**
         * 当前轮播视图的单元格起止索引
         * @return {{start: number, end: number}}
         */
        viewCellIndexRange() {
            let cellCountPerView = this.cellCountPerColumn*this.columnCountPerView;
            let start = cellCountPerView * (this.curView-1);
            let end = start+cellCountPerView;
            return {start, end};
        },
        /**
         * 当前轮播视图的单元格dom数组
         */
        viewCellDoms() {
            let {start, end} = this.viewCellIndexRange;
            return this.cellDoms.slice(start, end);
        },
        /**
         * 当前轮播视图的单元格数据
         * @return {T[]}
         */
        viewCells() {
            let {start, end} = this.viewCellIndexRange;
            return this.cells.slice(start, end);
        },
        cellStyle() {
            let style = {};
            if(this.disabled){
                style.cursor = 'default';
            }
            return style;
        }
    },
    template: `
        <div class="xs-cell-selector" :style="boxSelectorStyle" ref="cellSelector">
            <div class="column-header">
                <slot name="view-buttons">
                    <div class="header-view-btn preview" @click="previewView" :class="{disabled: curView===1}"><slot name="preview-button"><i class="el-icon-arrow-left"></i></slot></div>
                    <div class="header-view-btn next" @click="nextView" :class="{disabled: curView===viewCount}"><slot name="next-button"><i class="el-icon-arrow-right"></i></slot></div>
                </slot>
                <div class="column-header-wrap" :style="headerWrapStyle">
                    <ul v-for="vc in viewCount" :key="'header-view-'+vc" :id="'xsCellSelectorHeaderView'+vc" class="column-header-view">
                        <li v-for="h in viewColumns(vc)" :key="'column-header-'+h" class="column-header-item" :style="columnHeaderStyle" @click="__innerToggleColumn(h)">{{columnHeaderValue(h)}}</li>
                        <!-- 每个轮播视图不满 columnCountPerView 列数时，补满 -->
                        <li v-for="e in viewEmptyColumnCount(vc)" :key="'fill-column-header-'+vc+'-'+e" class="column-header-item" :style="emptyFillStyle"></li>
                    </ul>
                </div>
            </div>
            <div class="rh-main-panel" ref="mainPanel">
                <ul class="row-header">
                    <li v-for="r in rowCount" :key="'row-header-'+r" :style="rowHeaderStyle"><slot name="row-header-value" :num="r">{{rowHeaderValue(r)}}</slot></li>
                </ul>
                <div class="cell-container" ref="cellContainer" :style="cellContainerStyle">
                    <!-- 动态生成的拖拽选框 -->
                    <div v-if="showDragRect" ref="dragRect" class="selector-drag-rect" :class="{animate:animate}" :style="dragRectStyle"></div>
                    <ul v-for="vc in viewCount" :key="'cell-view-'+vc" :id="'xsCellSelectorCellView'+vc" class="cell-view">
                        <li v-for="h in viewColumns(vc)" :key="'column-cell-'+h" class="column-cell-item" :style="columnCellStyle">
                            <div v-for="cell in columnCells(h)" :key="'cell-'+cell[uniqueKey]" class="xs-cell-wrap" @click="toggleCell(cell)">
                                <slot name="cell" :cell="cell">
                                    <div class="xs-cell" :class="cellClass(cell)" :tmp="cell.__tempSelected" :style="cellStyle"></div>
                                </slot>
                            </div>
                        </li>
                        <!-- 每个轮播视图不满 columnCountPerView 列数时，补满 -->
                        <li v-for="e in viewEmptyColumnCount(vc)" :key="'fill-column-cell-'+vc+'-'+e" class="column-cell-item" :style="emptyFillStyle"></li>
                    </ul>
                </div>
            </div>
        </div>
    `,
    created() {
        cellSelectorUtil.createStyle();
        this.initCells();
    },
    mounted() {
        this.initCellStyleData();
        window.addEventListener('resize', this.initCellStyleData);
    },
    watch: {
        curView: {
            handler: function (newView) {
                let scrollLeft = this.cellsContainerWidth*(newView-1);//滚动到的目标位置
                this.cellsContainerScrollLeft = scrollLeft;
                document.querySelector('.column-header-wrap').scrollTo({left:scrollLeft, behavior:'smooth'});//滚动头部容器
                document.querySelector('.cell-container').scrollTo({left:scrollLeft, behavior:'smooth'});//滚动穴盘容器
            }
        },
        disabled: {
            handler: function (newValue) {
                newValue ? this.__removeWindowEvents() : this.__addWindowEvents();
            },
            immediate: false
        },
        cells: {
            handler: function (newCells) {
                this.$emit('select', newCells);
            },
            deep: true
        }
    },
    methods: {
        /**
         * 根据value、columnCount、rowCount、uniqueKey 初始组件内部cells数组
         */
        initCells() {
            let value = this.value || [];
            let uniqueKey = this.uniqueKey || 'id';
            let maxId = value.reduce((max, v)=>{return Math.max(max, v[uniqueKey])}, 0);
            let cells = [];
            for(let i=0; i<this.cellCount; i++) {
                let cell = value[i] || {};
                if(!cell.hasOwnProperty(uniqueKey)){
                    cell[uniqueKey] = ++maxId;
                }
                if(!cell.hasOwnProperty('selected')) {
                    this.$set(cell, 'selected', false);
                }
                if(!cell.hasOwnProperty('disabled')) {
                    this.$set(cell, 'disabled', false);
                }
                cells.push(cell);
            }
            this.cells = cells;
        },
        initCellStyleData() {
            this.$nextTick(()=>{
                this.cellsContainerWidth = document.querySelector('.xs-cell-selector .cell-container').offsetWidth;
                this.cellsContainerHeight = document.querySelector('.xs-cell-selector .row-header').offsetHeight;
                this.$nextTick(()=>{
                    //一开始是没有滚动条的， cellsContainerWidth = 100% - 除左侧行标题宽度；
                    //需要等渲染完后，再次计算，此时 cellsContainerWidth = 100% - 除左侧行标题宽度 - 滚动条宽度；
                    //如果不进行再次计算，列头标题会出现偏移
                    this.cellsContainerWidth = document.querySelector('.xs-cell-selector .cell-container').offsetWidth;
                    this.columnWidth = document.querySelector('.xs-cell-selector .column-cell-item').offsetWidth;
                });
                this.mainPanelRect = this.$refs.mainPanel.getBoundingClientRect();
                this.cellContainerRect = this.$refs.cellContainer.getBoundingClientRect();
                this.cellDoms = Array.from(document.querySelectorAll('.xs-cell-selector .xs-cell-wrap'));

                if(!this.disabled) {
                    this.__addWindowEvents();
                }
            });
        },
        /**
         * 行头标题
         * @param r
         * @return {string}
         */
        rowHeaderValue(r) {
            return (r+'').padStart(2, '0')+this.rowUnit;
        },
        /**
         * 单元动态class
         * @param cell
         * @return {string}
         */
        cellClass(cell) {
            if(cell.disabled){
                return 'disabled';
            }else if(!this.isReverse && (cell.selected || cell.__tempSelected)){
                return 'selected';
            }else if(this.isReverse && cell.selected && !cell.__tempSelected) {
                return 'selected';
            }else {
                return '';
            }
        },
        /**
         * 某个视图的列数据(索引+1)
         */
        viewColumns(viewNum) {
            return this.viewColumnsMap.get(viewNum);
        },
        /**
         * 每个视图 不满 columnCountPerView 列时，需要补满的列数
         * @param viewNum
         * @return {number}
         */
        viewEmptyColumnCount(viewNum) {
            let vcl = this.viewColumns(viewNum).length;
            return this.columnCountPerView - vcl;
        },
        /**
         * 列头标题
         * @param c
         * @return {string}
         */
        columnHeaderValue(c) {
            return (c+'').padStart(2, '0')+this.columnUnit;
        },
        /**
         * 某一大列的单元格数据
         * @param columnNum
         */
        columnCells(columnNum) {
            let start = this.cellCountPerColumn*(columnNum-1);
            let end = start + this.cellCountPerColumn;
            return this.cells.slice(start, end);
        },
        __clearSelection() {
            document.selection && document.selection.empty && ( document.selection.empty(), 1)
            || window.getSelection && window.getSelection().removeAllRanges();
        },
        __addWindowEvents() {
            this.__removeWindowEvents();
            this.$refs.cellSelector.addEventListener('mousedown', this.__mousedown);
        },
        __addWindowEvents_mousemove_mouseup() {
            this.__removeWindowEvents_mousemove_mouseup();
            this.$refs.cellSelector.addEventListener('mousemove', this.__mousemove);
            this.$refs.cellSelector.addEventListener('mouseup', this.__mouseup);
        },
        __removeWindowEvents() {
            this.$refs.cellSelector.removeEventListener('mousedown', this.__mousedown);
            this.__removeWindowEvents_mousemove_mouseup();
        },
        __removeWindowEvents_mousemove_mouseup() {
            this.$refs.cellSelector.removeEventListener('mousemove', this.__mousemove);
            this.$refs.cellSelector.removeEventListener('mouseup', this.__mouseup);
        },
        __getEventPoint(e) {
            let offsetTop = e.clientY - this.mainPanelRect.top;
            let y = offsetTop + this.$refs.mainPanel.scrollTop;
            let x = e.clientX - this.cellContainerRect.left;
            if(x>this.cellContainerRect.width){
                x = this.cellContainerRect.width;
            }
            if(x<0){
                x = 0;
            }
            return {x, y};
        },
        __mousedown(e) {
            if (this.disabled) return;
            this.__clearSelection();
            this.__addWindowEvents_mousemove_mouseup();
            if(this.dragSelectedCells && this.dragSelectedCells.size>0) {
                this.dragSelectedCells.forEach(c=>{
                    c.__tempSelected = false;
                });
            }
            this.startPoint = this.__getEventPoint(e);
            this.dragSelectedCells = new Set();
        },
        __mousemove(e) {
            if (this.disabled || this.busy) return;
            //console.log(this.startPoint, e.clientX, e.clientY);
            if(this.startPoint) {
                this.busy = true;
                this.endPoint = this.__getEventPoint(e);
                this.$nextTick(()=>{
                    //console.log(this.$refs.dragRect)
                    let selectedCells = this.__getSelectedCells();
                    this.dragSelectedCells.forEach(oldCell => {
                        if(!selectedCells.has(oldCell)) {//前一次被框选，本次没框住
                            oldCell.__tempSelected = false;
                        }
                    });
                    this.dragSelectedCells = selectedCells;
                    this.busy = false;
                });
            }
        },
        __mouseup(e) {
            if (this.disabled) return;
            //console.log('startPoint=', JSON.stringify(this.startPoint), 'endPoint=', JSON.stringify(this.endPoint));
            //console.log(JSON.stringify(this.dragRectStyle))
            this.__removeWindowEvents_mousemove_mouseup();
            let checkKeep = true;
            let upIsReverse = false;
            if(this.startPoint){
                let upPoint = this.__getEventPoint(e);
                if(upPoint.x===this.startPoint.x && upPoint.y===this.startPoint.y){
                    checkKeep = false;
                }
                upIsReverse = this.reverse && upPoint.y<this.startPoint.y;
            }
            this.startPoint = null;
            this.endPoint = null;
            if(checkKeep && !this.keep){  //开始和结束是同一个点时(比如点击)，keep=false时，不清空
                this.cells.forEach(c => c.selected=false);
            }
            this.dragSelectedCells.forEach(c => {
                if(!c.disabled){
                    if(upIsReverse) {    //当前反选，不选中,此处不用this.isReverse，因为鼠标松开后，this.isReverse===false
                        c.selected = false;
                    }else {
                        c.selected = true;
                    }
                }
                c.__tempSelected = false;
            });
            //this.dragSelectedCells = null;
            this.busy = false;
            //console.log(this.cells)
        },
        /**
         * 获取被选中单元格对象
         */
        __getSelectedCells() {
            let r = new Set();
            for (let i = 0; i < this.viewCells.length; i++) {
                let selected = this.__isCrash(this.viewCellDoms[i]);
                if(selected) {
                    this.viewCells[i].__tempSelected = true;
                    r.add(this.viewCells[i]);
                }
            }
            return r;
        },
        /**
         * 碰撞检测
         * @param targetDom
         * @return {boolean|boolean}
         */
        __isCrash(targetDom) {
            return cellSelectorUtil.isCrash(targetDom, this.$refs.dragRect);
        },
        __innerToggleColumn(column) {
            if(this.disabled || this.disableHeaderSelect) return;
            this.toggleColumn(column);
        },
        /**
         * 选中、取消选中某些单元格
         * @param cells
         */
        __toggleSelectCells(cells) {
            let selectableCells = cells.filter(c => !c.disabled);
            let firstNotSelectedCell = selectableCells.find(c => !c.selected);
            if(firstNotSelectedCell) {  //cells存在没有被选中的单元格，则执行全选操作
                selectableCells.forEach(c => c.selected = true);
            }else {//cells都被选中了，执行取消选中操作
                selectableCells.forEach(c => c.selected = false);
            }
        },
        /**
         * 显示上一个视图
         */
        previewView() {
            if(this.curView<=1){
                return;
            }
            this.curView--;
        },
        /**
         * 显示下一个视图
         */
        nextView() {
            if(this.curView>=this.viewCount){
                return;
            }
            this.curView++;
        },
        /**
         * 获取某一列的所有单元格
         * @param column
         */
        getColumnCells(column) {
            if(column && column<=this.columnCount) {
                let startIndex = this.cellCountPerColumn*(column-1);
                let endIndex = startIndex+this.cellCountPerColumn;
                return this.cells.slice(startIndex, endIndex);
            }else {
                return [];
            }
        },
        /**
         * 选中、取消选中某一列
         * @param column
         * @param startRow
         * @param endRow
         */
        toggleColumn(column, startRow, endRow) {
            let columnCells = this.getColumnCells(column);
            if(columnCells.length>0) {
                let startIndex = 0, endIndex = columnCells.length;
                if(startRow && startRow<=this.rowCount) {
                    startIndex = this.cellColumnCountPerColumn*(startRow-1);
                }
                if(endRow && endRow<=this.rowCount) {
                    endIndex = this.cellColumnCountPerColumn * endRow;
                }
                if(endIndex>startIndex){
                    columnCells = columnCells.slice(startIndex, endIndex);
                    this.__toggleSelectCells(columnCells);
                }
            }
        },
        /**
         * 选中、取消选中某个单元格
         * @param cell
         */
        toggleCell(cell) {
            if(this.disabled || cell.disabled){
                return;
            }
            cell.selected = !cell.selected;
        }
    }
};
Vue.component('xs-cell-selector', xsCellSelector);

(function(root, factory){
    root.cellSelectorUtil = factory('cellSelectorUtil');
})(window, function (cellSelectorUtil) {
    return {
        /**
         * 碰撞检测
         * @param targetDom 目标对象（即将要被碰撞的元素）
         * @param moveDom 移动的对象（可能是拖拽移动，也可能是其他原因导致其移动）
         */
        isCrash: function (targetDom, moveDom) {
            if (targetDom === moveDom) return false;//如果目标对象和移动对象是同一个，返回未接触
            let tr = targetDom.getBoundingClientRect(), mr = moveDom.getBoundingClientRect();
            let t = { x1: tr.x, x2: tr.x + tr.width, y1: tr.y, y2: tr.y + tr.height };//目标对象的四角顶点坐标
            let m = { x1: mr.x, x2: mr.x + mr.width, y1: mr.y, y2: mr.y + mr.height };//移动对象的四角顶点坐标
            let a = { w: Math.min(t.x2, m.x2) - Math.max(t.x1, m.x1), h: Math.min(t.y2, m.y2) - Math.max(t.y1, m.y1) };//计算相交部分的宽度和高度
            let area = (a.w > 0 ? a.w : 0) * (a.h > 0 ? a.h : 0);//计算相交部分的面积
            return area ? true : false;//面积＞0，即碰撞（这里可以根据业务需求，改成相交部分面积＞具体的值才作为碰撞判断）
        },
        /**
         * 动态创建样式
         */
        createStyle: function (){
            if(document.getElementById('cell-selector-style')){
                return;
            }
            let css = `
            .xs-cell-selector{
                --column-header-height: 30px;
                --column-cell-padding: 4px;
                --row-header-width: 30px;
                --row-padding: 4px;
                --header-view-btn-size: 28px;
                --drag-rect-border-width: 1px;
                --drag-rect-border-color: #F56C6C;
                --drag-rect-border-style: solid;
                --drag-rect-bg-color: #F56C6C22;
                --cell-size: 25px;
                --cell-border-width: 1px;
                --cell-border-color: #3CF1FF;
                --cell-selected-color: #3CF1FF;
                --cell-disabled-color: #F1C61B;
                --view-padding: 10px;
    
                position: relative;
                display: flex;
                flex-direction: column;
                overflow: hidden;
                color: #fff;
            }
            .xs-cell-selector * {
                box-sizing: border-box;
            }
            .xs-cell-selector .column-header{
                position: relative;
                display: flex;
                width: 100%;
                height: var(--column-header-height);
                padding-left: var(--row-header-width);
                overflow: hidden;
                user-select: none;
            }
            .xs-cell-selector .header-view-btn{
                position: absolute;
                width: var(--header-view-btn-size);
                height: var(--header-view-btn-size);
                top: 50%;
                transform: translateY(-50%);
                display: flex;
                align-items: center;
                justify-content: center;
                cursor: pointer;
                font-size: 20px;
            }
            .xs-cell-selector .header-view-btn.disabled{
                cursor: not-allowed;
            }
            .xs-cell-selector .header-view-btn.preview{
                left: 0;
            }
            .xs-cell-selector .header-view-btn.next{
                right: 0;
            }
            .xs-cell-selector .column-header-wrap{
                display: flex;
                height: 100%;
                overflow-y: hidden;
                overflow-x: auto;
            }
            .xs-cell-selector .column-header-wrap::-webkit-scrollbar,.xs-cell-selector .cell-container::-webkit-scrollbar{
                width: 0;
                height: 0;
            }
            .xs-cell-selector .column-header-view{
                height: 100%;
                width: 100%;
                overflow: hidden;
                display: flex;
                align-items: center;
                justify-content: space-between;
                flex-shrink: 0;
                padding: 0 var(--view-padding);
            }
            .xs-cell-selector .column-header-item{
                overflow: hidden;
                display: flex;
                align-items: center;
                justify-content: center;
                cursor: pointer;
            }
            .xs-cell-selector .rh-main-panel{
                flex: 1;
                width: 100%;
                overflow-x: hidden;
                overflow-y: auto;
                display: flex;
                align-items: flex-start;
            }
            .xs-cell-selector .row-header{
                padding: var(--row-padding) 0;
                width: var(--row-header-width);
                height: auto;
                display: grid;
                grid-template-columns: var(--row-header-width);
                grid-row-gap: calc(var(--row-padding)*2);
            }
            .xs-cell-selector .row-header li{
                display: flex;
                align-items: center;
                justify-content: center;
                height: var(--cell-size);
                user-select: none;
                /*border: 1px solid #000000;*/
            }
            .xs-cell-selector .cell-container{
                position: relative;
                flex: 1;
                overflow-y: hidden;
                overflow-x: auto;
                display: flex;
            }
            .xs-cell-selector .cell-container .cell-view{
                height: 100%;
                width: 100%;
                flex-shrink: 0;
                padding: 0 var(--view-padding);
                display: flex;
                justify-content: space-between;
            }
            .xs-cell-selector .cell-container .column-cell-item{
                padding: var(--row-padding) 0;
                display: inline-grid;
                grid-column-gap: calc(var(--column-cell-padding)*2);
                grid-row-gap: calc(var(--row-padding)*2);
            }
            .xs-cell-selector .xs-cell-wrap{
                overflow: hidden;
                display: flex;
                width: var(--cell-size);
                height: var(--cell-size);
                align-items: center;
                justify-content: center;
                background-color: #031F17;
            }
            .xs-cell-selector .xs-cell{
                overflow: hidden;
                width: 100%;
                height: 100%;
                border: var(--cell-border-width) solid var(--cell-border-color);
                border-radius: 2px;
                cursor: pointer;
                user-select: text;
                display: flex;
                align-items: center;
                justify-content: center;
            }
            .xs-cell-selector .xs-cell.selected{
                border-color: var(--cell-selected-color);
                background-color: var(--cell-selected-color);
            }
            .xs-cell-selector .xs-cell.disabled{
                border-color: var(--cell-disabled-color);
                background-color: var(--cell-disabled-color);
                cursor: default;
            }
            .xs-cell-selector .selector-drag-rect{
                position: absolute;
                z-index: 999;
                box-sizing: border-box;
                border: var(--drag-rect-border-width) var(--drag-rect-border-style) var(--drag-rect-border-color);
                background-color: var(--drag-rect-bg-color);
            }
            .xs-cell-selector .selector-drag-rect.animate{
                border: none;
                background: linear-gradient(90deg, var(--drag-rect-border-color) 60%, transparent 60%) repeat-x left top/10px var(--drag-rect-border-width),
                linear-gradient(0deg, var(--drag-rect-border-color) 60%, transparent 60%) repeat-y right top/var(--drag-rect-border-width) 10px,
                linear-gradient(90deg, var(--drag-rect-border-color) 60%, transparent 60%) repeat-x right bottom/10px var(--drag-rect-border-width),
                linear-gradient(0deg, var(--drag-rect-border-color) 60%, transparent 60%) repeat-y left bottom/var(--drag-rect-border-width) 10px, var(--drag-rect-bg-color);
                animation: selector-rect-animate .382s infinite linear;
            }
            @keyframes selector-rect-animate {
                0% {
                    background-position: left top, right top, right bottom, left bottom;
                }
    
                100% {
                    background-position: left 10px top, right top 10px, right 10px bottom, left bottom 10px;
                }
            }
            `;
            let head = document.getElementsByTagName('head')[0];
            let style = document.createElement('style');
            style.id = 'cell-selector-style';
            style.appendChild(document.createTextNode(css));
            head.appendChild(style);
        }
    }
});
